package com.flyan.game.motafx.core.util.entity;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.SpawnData;
import com.flyan.game.motafx.core.consts.PropertyConsts;
import com.flyan.game.motafx.core.enums.EntityClassifyEnum;
import com.flyan.game.motafx.core.enums.EntityTypeEnum;
import com.flyan.game.motafx.core.map.MapPosition;
import com.flyan.game.motafx.core.util.position.PositionUtils;
import javafx.geometry.Point2D;

/**
 * 实体实用工具
 *
 * @author flyan
 * @version 1.0
 * @email flyan_by_chenu@sina.com
 * @since 2025/1/31
 */
public class EntityUtils {

    private EntityUtils() {  }

    /**
     * 生成实体到地图上
     *
     * @param entityType 实体类型
     * @param row 行号，从第一行开始
     * @param col 列号，从第一列开始
     * @return 实体
     */
    public static Entity spawnToMap(EntityTypeEnum entityType, int row, int col) {
        return spawnToMap(entityType, new MapPosition(row, col));
    }

    /**
     * 生成实体到地图上
     *
     * @param entityType 实体类型
     * @param position  地图位置
     * @param isActive 实体是否活跃（不活跃仅创建不加入游戏世界）
     * @param info 实体信息
     * @return 实体
     */
    public static Entity spawnToMap(EntityTypeEnum entityType, MapPosition position, boolean isActive, JSONObject info) {
        Point2D mapPosition = PositionUtils.getMapPosition(position);
        assert mapPosition != null;
        if (info == null) {
            info = new JSONObject();
        }
        info.set("entityCode", entityType.getCode()); // 设置实体编码
        if (StrUtil.isEmpty((String) info.get("name"))) { // 没有名称，默认使用实体类型名称
            info.set("name", entityType.getName());
        }
        String entityName = entityType.getClassify().name(); // 通过实体分类生成，由地图提供的实体实体参数决定实体属性
        /* @TODO flyan 地形还玩完全完成拆解 */
        if (entityType.getClassify() == EntityClassifyEnum.TERRAIN) {
            entityName = entityType.name();
        }
        return isActive
                ? FXGL.spawn(entityName, new SpawnData(mapPosition).put(PropertyConsts.ENTITY_INFO, info))
                : FXGL.getGameWorld().create(entityName, new SpawnData(mapPosition).put(PropertyConsts.ENTITY_INFO, info));
    }

    public static Entity spawnToMap(EntityTypeEnum entityType, MapPosition position, JSONObject info) {
        return spawnToMap(entityType, position, true, info);
    }

    /**
     * 生成实体到地图上
     *
     * @param entityType 实体类型
     * @param position  地图位置
     * @return 实体
     */
    public static Entity spawnToMap(EntityTypeEnum entityType, MapPosition position) {
        return spawnToMap(entityType, position, null);
    }

    /**
     * 获取实体信息
     *
     * @param entity 实体
     * @param clazz 实体信息类型
     * @return 实体信息
     * @param <T> 实体信息类型
     */
    public static <T> T getEntityInfo(Entity entity, Class<T> clazz) {
        JSONObject info = entity.getObject(PropertyConsts.ENTITY_INFO);
        return info.toBean(clazz);
    }

    /**
     * 从实体生成数据中获取实体信息
     *
     * @param spawnData 实体生成数据
     * @param clazz 实体信息类型
     * @return 实体信息
     * @param <T> 实体信息类型
     */
    public static <T> T getEntityInfoFromSpawnData(SpawnData spawnData, Class<T> clazz) {
        JSONObject info = spawnData.get("info");
        return info.toBean(clazz);
    }

    /**
     * 获取实体属性，其属性都在实体信息中
     *
     * @param entity 实体
     * @param propertyName 实体新增中的属性，可给对象路径表达式，例如 a.b.c
     * @param clazz 属性类型
     * @return 属性
     * @param <T> 属性类型
     */
    public static <T> T getEntityProperty(Entity entity, String propertyName, Class<T> clazz) {
        JSONObject info = entity.getObject(PropertyConsts.ENTITY_INFO);
        if (info != null) {
            return info.getByPath(propertyName, clazz);
        }
        return null;
    }

}
